#!/bin/bash

clear

print_ascii_art() {
    cat << EOF
 ███████╗███████╗██████╗        █████╗ ██╗
 ██╔════╝██╔════╝██╔══██╗      ██╔══██╗██║
 █████╗  ███████╗██████╔╝█████╗███████║██║
 ██╔══╝  ╚════██║██╔═══╝ ╚════╝██╔══██║██║
 ███████╗███████║██║           ██║  ██║██║
 ╚══════╝╚══════╝╚═╝           ╚═╝  ╚═╝╚═╝
EOF
}

print_version() {
    echo -e "\033[32m   当前服务端版本:v2.20.17\033[0m"
    
    echo -e "\033[32m   脚本开源地址:https://gitee.com/zhuxiaohuaqn/ESP-AI-CLI\033[0m"
    
}

print_run_count() {
    response=$(curl -s GET "https://www.qingningz.cn/espapi.php")
    echo -e "\033[32m   脚本已被运行了 $response 次了！快来使用吧！\033[0m"
}

print_info() {
    echo -e "\033[36m------------------------------------------------------------------------------\033[0m"
    echo ""
    echo -e "\033[31m欢迎使用 ESP-AI\033[0m"
    echo -e "\033[31m请使用root用户运行此脚本!\033[0m"
    echo ""
    echo -e "\033[34m官方文档:https://espai.fun\033[0m"
    echo ""
    echo -e "\033[34m本脚本来源于青柠博客:https://www.qingningz.cn\033[0m"
    echo ""
    echo -e "\033[34m如果你想手动安装,请看保姆教程:https://www.qingningz.cn/archives/2231\033[0m"
    echo ""
    echo -e "\033[32m脚本采用 docker 形式安装,不会对当前环境造成影响，请放心使用\033[0m"
    echo ""
    echo -e "\033[32m请确保您已经注册并获取了讯飞开放平台的 appid,apiSecret,apiKey\033[0m"
    echo ""
    echo -e "\033[35m------------------------------------------------------------------------------\033[0m"
}
# amd安装esp-ai
get_xfyun_params() {
    clear
    echo -e "\033[31m由于目前版本,语音识别只支持讯飞，所以你没有更多选择\033[0m"
    echo -e "\033[31m但你可以在安装完成后通过脚本的高级选项去更改大语言模型和语音合成\033[0m"
    echo -e "\033[32m 接下来你只需输入讯飞参数进行安装\033[0m"
    echo -e "\033[36m------------------------------------------------------------------------------\033[0m"
    echo -e "\033[32m请输入讯飞的参数：\033[0m"
    read -p "appid: " appid
    read -p "apiSecret: " apiSecret
    read -p "apiKey: " apiKey
    read -p "请输入外网端口：" external_port
    # 将讯飞的参数保存到 config.txt 文件中
    echo "appid=$appid" > config.txt
    echo "apiSecret=$apiSecret" >> config.txt
    echo "apiKey=$apiKey" >> config.txt
}

create_index_js() {
    # 创建 index.js 文件并保存参数
cat > index.js <<EOF
const espAi = require("esp-ai"); 
const config = { 
    gen_client_config: ()=>({

        // 调用讯飞语音识别
        iat_server: "xun_fei",
        iat_config: {
            // 讯飞：https://console.xfyun.cn/services/iat  。打开网址后，右上角三个字段复制进来即可。
            appid: "${appid}",
            apiSecret: "${apiSecret}",
            apiKey: "${apiKey}", 
        },

        // 调用火山引擎LLM
        llm_server: "xun_fei",
        llm_config: {
            // 1. 注册：https://console.volcengine.com/ark
            // 1. 开通: https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement?LLM=%7B%7D&tab=LLM
            // 2. 创建接入点: https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint
            appid: "${appid}",
            apiSecret: "${apiSecret}",
            apiKey: "${apiKey}", 
            llm: "v4.0",
        },

        // 调用火山引擎TTS
        tts_server: "xun_fei",
        tts_config: {
            // 1. 注册：https://console.volcengine.com/speech/app
            // 2. 音色开通： https://console.volcengine.com/speech/service/8?AppID=6359932705
            // 3. 授权： xxx
            // 服务接口认证信息
            appid: "${appid}",
            apiSecret: "${apiSecret}",
            apiKey: "${apiKey}", 
        },


    })
};

const espAiIns = espAi(config);

// 在合适的时机可以调用方法来在服务端实现设备操作
// espAiIns.restart("[device_id]") // 重启设备
// espAiIns.tts("[device_id]", "你好啊")   // 让设备说话
// ...
EOF

}
# amd离线安装docker
install_docker() {
    if which docker >/dev/null 2>&1; then
        echo -e "\033[32m检测到 Docker 已安装，跳过安装步骤\033[0m"
        echo "启动 Docker "
        systemctl start docker 2>&1 | tee -a "${CURRENT_DIR}"/install.log
    else
       
        echo -e "\033[31m未检测到 Docker,开始安装 Docker\033[0m"
        echo "下载 Docker 安装包"
        rm -rf docker.tar
        sudo apt-get wget -y
        wget  https://vip.123pan.cn/1812503341/esp32%E7%8E%AF%E5%A2%83/docker.tar
        tar -xvf docker.tar
        if [ $? -eq 0 ]; then
            echo "解压成功"
        else
            echo "解压失败"
            exit 1
        fi
        echo "... 离线安装 docker"
        chmod +x docker/bin/*
        cp docker/bin/* /usr/bin/
        cp docker/service/docker.service /etc/systemd/system/
        chmod 754 /etc/systemd/system/docker.service
        mkdir -p /etc/docker/
        cp docker/conf/daemon.json /etc/docker/daemon.json
        echo "... 启动 docker"
        systemctl enable docker; systemctl daemon-reload; systemctl start docker
    fi
}
# arm64位安装docker 注意这里引用1panel脚本
function armInstall_Docker(){
    if which docker >/dev/null 2>&1; then
        log "检测到 Docker 已安装，跳过安装步骤"
        configure_accelerator
    else
        log "... 在线安装 docker"

        if [[ $(curl -s ipinfo.io/country) == "CN" ]]; then
            sources=(
                "https://mirrors.aliyun.com/docker-ce"
                "https://mirrors.tencent.com/docker-ce"
                "https://mirrors.163.com/docker-ce"
                "https://mirrors.cernet.edu.cn/docker-ce"
            )

            docker_install_scripts=(
                "https://get.docker.com"
                "https://testingcf.jsdelivr.net/gh/docker/docker-install@master/install.sh"
                "https://cdn.jsdelivr.net/gh/docker/docker-install@master/install.sh"
                "https://fastly.jsdelivr.net/gh/docker/docker-install@master/install.sh"
                "https://gcore.jsdelivr.net/gh/docker/docker-install@master/install.sh"
                "https://raw.githubusercontent.com/docker/docker-install/master/install.sh"
            )

            get_average_delay() {
                local source=$1
                local total_delay=0
                local iterations=2
                local timeout=2
    
                for ((i = 0; i < iterations; i++)); do
                    delay=$(curl -o /dev/null -s -m $timeout -w "%{time_total}\n" "$source")
                    if [ $? -ne 0 ]; then
                        delay=$timeout
                    fi
                    total_delay=$(awk "BEGIN {print $total_delay + $delay}")
                done
    
                average_delay=$(awk "BEGIN {print $total_delay / $iterations}")
                echo "$average_delay"
            }
    
            min_delay=99999999
            selected_source=""
    
            for source in "${sources[@]}"; do
                average_delay=$(get_average_delay "$source" &)
    
                if (( $(awk 'BEGIN { print '"$average_delay"' < '"$min_delay"' }') )); then
                    min_delay=$average_delay
                    selected_source=$source
                fi
            done
            wait

            if [ -n "$selected_source" ]; then
                log "选择延迟最低的源 $selected_source，延迟为 $min_delay 秒"
                export DOWNLOAD_URL="$selected_source"
                
                for alt_source in "${docker_install_scripts[@]}"; do
                    log "尝试从备选链接 $alt_source 下载 Docker 安装脚本..."
                    if curl -fsSL --retry 2 --retry-delay 3 --connect-timeout 5 --max-time 10 "$alt_source" -o get-docker.sh; then
                        log "成功从 $alt_source 下载安装脚本"
                        break
                    else
                        log "从 $alt_source 下载安装脚本失败，尝试下一个备选链接"
                    fi
                done
                
                if [ ! -f "get-docker.sh" ]; then
                    log "所有下载尝试都失败了。您可以尝试手动安装 Docker，运行以下命令："
                    log "bash <(curl -sSL https://linuxmirrors.cn/docker.sh)"
                    exit 1
                fi

                sh get-docker.sh 2>&1 | tee -a ${CURRENT_DIR}/install.log

                docker_config_folder="/etc/docker"
                if [[ ! -d "$docker_config_folder" ]];then
                    mkdir -p "$docker_config_folder"
                fi
                
                docker version >/dev/null 2>&1
                if [[ $? -ne 0 ]]; then
                    log "docker 安装失败\n您可以尝试使用离线包进行安装，具体安装步骤请参考以下链接：https://1panel.cn/docs/installation/package_installation/"
                    exit 1
                else
                    log "docker 安装成功"
                    systemctl enable docker 2>&1 | tee -a "${CURRENT_DIR}"/install.log
                    configure_accelerator
                fi
            else
                log "无法选择源进行安装"
                exit 1
            fi
        else
            log "非中国大陆地区，无需更改源"
            export DOWNLOAD_URL="https://download.docker.com"
            curl -fsSL "https://get.docker.com" -o get-docker.sh
            sh get-docker.sh 2>&1 | tee -a "${CURRENT_DIR}"/install.log

            log "... 启动 docker"
            systemctl enable docker; systemctl daemon-reload; systemctl start docker 2>&1 | tee -a "${CURRENT_DIR}"/install.log

            docker_config_folder="/etc/docker"
            if [[ ! -d "$docker_config_folder" ]];then
                mkdir -p "$docker_config_folder"
            fi

            docker version >/dev/null 2>&1
            if [[ $? -ne 0 ]]; then
                log "docker 安装失败\n您可以尝试使用安装包进行安装，具体安装步骤请参考以下链接：https://1panel.cn/docs/installation/package_installation/"
                exit 1
            else
                log "docker 安装成功"
            fi
        fi
    fi
}

function armInstall_Compose(){
    docker-compose version >/dev/null 2>&1
    if [[ $? -ne 0 ]]; then
        log "... 在线安装 docker-compose"
        
        arch=$(uname -m)
		if [ "$arch" == 'armv7l' ]; then
			arch='armv7'
		fi
		curl -L https://resource.fit2cloud.com/docker/compose/releases/download/v2.26.1/docker-compose-$(uname -s | tr A-Z a-z)-"$arch" -o /usr/local/bin/docker-compose 2>&1 | tee -a "${CURRENT_DIR}"/install.log
        if [[ ! -f /usr/local/bin/docker-compose ]];then
            log "docker-compose 下载失败，请稍候重试"
            exit 1
        fi
        chmod +x /usr/local/bin/docker-compose
        ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

        docker-compose version >/dev/null 2>&1
        if [[ $? -ne 0 ]]; then
            log "docker-compose 安装失败"
            exit 1
        else
            log "docker-compose 安装成功"
        fi
    else
        compose_v=$(docker-compose -v)
        if [[ $compose_v =~ 'docker-compose' ]];then
            read -p "检测到已安装 Docker Compose 版本较低（需大于等于 v2.0.0 版本），是否升级 [y/n] : " UPGRADE_DOCKER_COMPOSE
            if [[ "$UPGRADE_DOCKER_COMPOSE" == "Y" ]] || [[ "$UPGRADE_DOCKER_COMPOSE" == "y" ]]; then
                rm -rf /usr/local/bin/docker-compose /usr/bin/docker-compose
                Install_Compose
            else
                log "Docker Compose 版本为 $compose_v，可能会影响应用商店的正常使用"
            fi
        else
            log "检测到 Docker Compose 已安装，跳过安装步骤"
        fi
    fi
}




check_docker_installed() {
    if command -v docker >/dev/null 2>&1; then
        echo -e "\033[32m检测到 Docker 已安装，跳过安装步骤。\033[0m"
        # 尝试以更详细的方式启动 Docker，并捕获启动日志
        sudo systemctl start docker 2>&1 | tee /tmp/docker_start_log
        echo -e "\033[32m正在检查 Docker 是否成功启动...\033[0m"
        # 等待一段时间让 Docker 启动
        sleep 5
        # 检查 Docker 是否正在运行
        if docker info >/dev/null 2>&1; then
            echo -e "\033[32mDocker 启动成功。\033[0m"
        else
            echo -e "\033[31mDocker 启动失败。请检查 /tmp/docker_start_log 文件以获取更多信息。\033[0m"
            exit 1
        fi
    else
        echo -e "\033[31m未检测到 Docker，开始安装 Docker。\033[0m"
        curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -
    fi
}

configure_docker_mirror() {
    if curl -Is https://www.baidu.com | grep -q "200 OK"; then
        echo -e "\033[31m检测到为国内服务器。\033[0m"
        echo "配置国内服务器加速镜像..."
        sudo mkdir -p /etc/docker
        sudo tee /etc/docker/daemon.json <<EOF
    {
    "registry-mirrors": [https://docker.1panelproxy.com,https://docker.1panel.live]
    }
EOF
        sudo systemctl restart docker
    else
        echo -e "\033[32m非国内服务器。\033[0m"
    fi
}

pull_image() {
    if docker pull 2362400196/espai:v2.2.0; then
        echo -e "\033[32m镜像拉取成功。\033[0m"
    else
        echo -e "\033[31m镜像拉取失败。\033[0m"
        echo "进行第二次尝试..."
        if docker pull 2362400196/espai:v2.2.0; then
            echo -e "\033[32m第二次尝试镜像拉取成功。\033[0m"
        else
            echo -e "\033[31m第二次尝试镜像拉取也失败了。\033[0m"
            exit 1
        fi
    fi
}

arm64_install() {
    curl https://vip.123pan.cn/1812503341/esp32%E7%8E%AF%E5%A2%83/espai_arm.tar  -o espai_arm.tar
    docker load -i espai_arm.tar
    docker rm -f esp 2>/dev/null
    docker create --name esp -p 8088:8088 espai_arm:v2.2.0 node /opt/espai/index.js
    docker cp ./index.js esp:/opt/espai/index.js
    docker start esp
    
}

remove_existing_container() {
    if docker ps -a | grep "esp-ai"; then
        echo "正在删除已存在的名为 esp-ai 的容器..."
        docker rm -f esp-ai
    fi
}

start_container() {
    echo -e "\033[32m开始启动容器。\033[0m"
    docker create --name esp-ai -p "${external_port}:8088" 2362400196/espai:v2.2.0 node /opt/espai/index.js
    docker cp ./index.js esp-ai:/opt/espai/index.js
    docker start esp-ai
    clear
    echo -e "\033[32m容器启动成功。\033[0m"
    echo -e "\033[32m请在ESP32上配置你的ip和端口\033[0m"
    echo -e "\033[32m----------------------------------------------------\033[0m"
    
    ip_address=$(curl -s https://api.ipify.org)
    echo ""
    echo -e "\033[32mIP地址: $ip_address\033[0m"
    echo -e "\033[32m端 口:${external_port}\033[0m"
    echo ""
    echo -e "\033[32m----------------------------------------------------\033[0m"
    
}

advanced_options() {
    echo -e "\033[33m高级选项菜单:\033[0m"
    echo ""
    echo -e "   ★ 1. 查看ESP-AI状态"
    echo ""
    echo -e "   ★ 2. 停止ESP-AI"
    echo ""
    echo -e "   ★ 3. 重启ESP-AI"
    echo ""
    echo -e "   ★ 4. 修改ESP-AI配置"
    echo ""
    read -p "请选择高级选项：" advanced_option
    case $advanced_option in
        1)
            if docker ps -a | grep "esp-ai" >/dev/null; then
                echo -e "\033[32mespai ESP-AI正在运行。\033[0m"
            else
                echo -e "\033[31mespai ESP-AI已停止。\033[0m"
            fi
            ;;
        2)
            docker stop esp-ai
            ;;
        3)
            docker restart esp-ai
            ;;
        4)
            rm -rf config.sh
            curl -o config.sh --silent --show-error --fail --location https://gitee.com/zhuxiaohuaqn/ESP-AI-CLI/raw/master/config.sh && chmod +x config.sh &&./config.sh
            ;;
        *)
            echo -e "\033[31m无效的选项。\033[0m"
            ;;
    esac
}
select_architecture() {
    echo -e "\033[33m请选择架构类型:\033[0m"
    echo ""
    echo -e "   ★ 1. adm架构"
    echo ""
    echo -e "   ★ 2. arm64位(树莓派，香橙派...)"
    echo ""
    read -p "请输入选项：" arch_choice
    case $arch_choice in
        1)
        #amd架构
            get_xfyun_params
            create_index_js
            install_docker
            configure_docker_mirror
            pull_image
            remove_existing_container
            start_container
            ;;
        2)
        #arm64位(树莓派，香橙派...)
            get_xfyun_params
            create_index_js
            armInstall_Docker
            armInstall_Compose
            arm64_install
            ;;
        *)
            echo -e "\033[31m无效的选项。\033[0m"
            ;;
    esac
}
main() {
    print_ascii_art
    echo ""
    echo ""
    print_version
    print_run_count
    print_info
    echo -e "\033[33m请选择操作:\033[0m"
    echo ""
    echo -e "   ★ 1. 安装 ESP-AI"
    echo ""
    echo -e "   ★ 2. 高级选项"
    echo ""
    read -p "请输入选项：" choice
    case $choice in
        1)

            select_architecture
            
            ;;
        2)
            advanced_options
            ;;
        *)
            echo -e "\033[31m无效的选项。\033[0m"
            ;;
    esac
}

main